#ifndef __THREADPOOL_HPP__
#define __THREADPOOL_HPP__ 


#include "LogMessage.hpp"
#include "caculator.hpp"
#include "Thread.hpp"
#include "lockGuard.hpp"

#include <queue>

const size_t DEFAULT_SIZE = 5;

template<class T>
class ThreadPool {
private:
  pthread_mutex_t* GetMutex() {
    return &_pmtx;
  }

  pthread_cond_t* GetCond() {
    return &_cpcond;
  }

  bool Empty() {
    return _taskQueue.empty();
  }

  T GetTask() {
    T task = _taskQueue.front();
    _taskQueue.pop();
    return task;
  }

  static void* Routine(void* arg) {
    Thread_name_and_Args* NA = reinterpret_cast<Thread_name_and_Args*>(arg);
    ThreadPool<T>* tp = reinterpret_cast<ThreadPool<T>*>(NA->getarg());

    while(true) {
      T task;
      {
        LockGuard lg(tp->GetMutex());
        
        while(tp->Empty()) {
          pthread_cond_wait(tp->GetCond(), tp->GetMutex());
        }

        task = tp->GetTask();

      }
      task(NA->getName());
    }
  }

public:
  ThreadPool(size_t size = DEFAULT_SIZE)
    :_size(size)
  {
    pthread_cond_init(&_cpcond, nullptr);
    pthread_mutex_init(&_pmtx, nullptr);

    for(int i = 0; i < _size; i++) {
      std::string name = "Thread:[";

      name += (std::to_string(i + 1) + "]");

      _threadPool.push_back(new Thread(name, Routine, this));

    }
  }

  void PushTask(const T& task) {
    LockGuard lg(&_pmtx);
    _taskQueue.push(task);
    pthread_cond_signal(&_cpcond);

  }

  void RunAllThread() {

    for(int i = 0; i < _size; i++) {
      _threadPool[i]->CreateThread();
      LogMessage(0, _F, _L, "%s启动成功",_threadPool[i]->getName().c_str());
    }
  }

  ~ThreadPool() {
    for(int i = 0; i < _size; i++) {
      _threadPool[i]->JoinThread();
      delete _threadPool[i];
    }
    pthread_mutex_destroy(&_pmtx);
    pthread_cond_destroy(&_cpcond);
  }
  
private:
  std::vector<Thread*> _threadPool;
  std::queue<T> _taskQueue;
  size_t _size;
  pthread_mutex_t _pmtx;
  pthread_cond_t _cpcond;
};


#endif 



